<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="style-util.html">
<link rel="import" href="style-transformer.html">
<link rel="import" href="style-defaults.html">

<!-- 

The `custom-style` extension of the native `<style>` element allows defining styles
in the main document that can take advantage of several special features of
Polymer's styling system:

* Document styles defined in a `custom-style` will be shimmed to ensure they do
not leak into local DOM when running on browsers without non-native Shadow DOM.
* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on
browsers without non-native Shadow DOM.
* Custom properties used by Polymer's shim for cross-scope styling
may be defined in an `custom-style`.

Example:

```html
<!doctype html>
<html>
<head>
  <script src="components/webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="components/polymer/polymer.html">

  <style is="custom-style">
    
    /* Will be prevented from affecting local DOM of Polymer elements */
    * {
      box-sizing: border-box;
    }
    
    /* Can use /deep/ and ::shadow combinators */
    body /deep/ .my-special-view::shadow #thing-inside {
      background: yellow;
    }
    
    /* Custom properties that inherit down the document tree may be defined */
    body {
      --my-toolbar-title-color: green;
    }
    
  </style>

</head>
<body>

    ...

</body>
</html>
```

Note, all features of `custom-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `custom-style` extension should only be used for defining document styles, outside of a custom element's local DOM.

-->

<script>
(function() {

  var nativeShadow = Polymer.Settings.useNativeShadow;
  var propertyUtils = Polymer.StyleProperties;
  var styleUtil = Polymer.StyleUtil;
  var styleDefaults = Polymer.StyleDefaults;
  var styleTransformer = Polymer.StyleTransformer;

  Polymer({

    is: 'custom-style',
    extends: 'style',

    created: function() {
      // NOTE: we cannot just check attached because custom elements in 
      // HTMLImports do not get attached.
      this._tryApply();
    },

    attached: function() {
      this._tryApply();
    },

    _tryApply: function() {
      if (!this._appliesToDocument) {
        // only apply variables iff this style is not inside a dom-module
        if (this.parentNode && 
          (this.parentNode.localName !== 'dom-module')) {
          this._appliesToDocument = true;
          // used applied element from HTMLImports polyfill or this
          var e = this.__appliedElement || this;
          styleDefaults.addStyle(e);
          // we may not have any textContent yet due to parser yielding
          // if so, wait until we do...
          if (e.textContent) {
            this._apply();
          } else {
            var observer = new MutationObserver(function() {
              observer.disconnect();
              this._apply();
            }.bind(this));
            observer.observe(e, {childList: true});
          }
        }
      }
    },

    // polyfill this style with root scoping and 
    // apply custom properties!
    _apply: function() {
      // used applied element from HTMLImports polyfill or this
      var e = this.__appliedElement || this;
      this._computeStyleProperties();
      var props = this._styleProperties;
      var self = this;
      e.textContent = styleUtil.toCssText(styleUtil.rulesForStyle(e), 
        function(rule) {
          var css = rule.cssText = rule.parsedCssText;
          if (rule.propertyInfo && rule.propertyInfo.cssText) {
            // TODO(sorvell): factor better
            // remove property assignments so next function isn't confused
            css = css.replace(propertyUtils.rx.VAR_ASSIGN, '');
            // replace with reified properties, scenario is same as mixin
            rule.cssText = propertyUtils.valueForProperties(css, props);
          }
          styleTransformer.documentRule(rule);
        }
      );
    }

  });

})();
</script>
